/*
 * RTSAI - Real-Time Strategy engine for AI research
 * Copyright(C) 2006 DIMAp-UFRN, licensed under LGPL
 *
 * Game core, where the simulation loop is implemented.
 */

#ifndef GAME_H_
#define GAME_H_

#include "Player.h"
#include "GameObject.h"
#include "Common.h"
#include "CppLua.h"
#include "Pool.h"

#include "OpenSteer/Clock.h"

using OpenSteer :: Clock;


/*! This class represents the core of the game. It's a singleton class where the
 *  simulation loop is implemented.
 */
class Game {

	public:
        /*! Returns the singleton game instance. */
		static Game& getInstance() {
		    if (!instance)
                instance = new Game();
		    // static Game instance;  // create only at the first time it is called
		    return (*instance);
        }

		/*! Pause the game loop */
		void pause() { paused = true; };

		/*! Re-start the game loop */
		void resume() { paused = false; };

		/*! Stop the game loop (game over) */
		void stop() { running = false; };

        bool update ();

        void init ( const char *file ) const;

        void reset ();

        // --- event related methods ---
        GameEvent* get_event ( const string &name );
        void register_event ( GameEvent *event );
        void unregister_event ( GameEvent *event );

        // --- player related methods ---
        Player& create_player() { return players.create(); }
        const Pool< Player >& get_players() const { return players; }

        int get_num_players ()  { return players.get_size(); }
        Player& get_player ( int id ) { return players[id]; }
        Player& get_player ( const string name );

        // --- static object related methods ---
        void add_obj ( GameObject *obj );
        void remove_obj ( GameObject *obj );
        GameObject* get_obj ( int i );
        int get_num_objs ();
        ObjectList* get_objs();

    public:
        /// Time since the beginning of the simulation. Updated by the game view.
        float current_time;

        /// Time since the last simulation iteration. Updated by the game view.
        float elapsed_time;

	private:
        static Game *instance;
		Game();
		Game ( const Game& ) { }  // copy constructor forbidden (private)
        void check_events();

        /// clock keeps track of both "real time" and "simulation time"
        Clock clock;

        /// A pool of players
        Pool < Player > players;
        /// indicate if the game is alive
        bool running;
        /// indicate is the game loop is pause
        bool paused;
        /// the registered events in the game
        EventList registered_events;
        /// static elements in the game
        ObjectList objects;
};

#endif /* GAME_H_*/
